home *** CD-ROM | disk | FTP | other *** search
- /* xllist - xlisp built-in list functions */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- #ifdef MEGAMAX
- overlay "overflow"
- #endif
-
- /* external variables */
- extern NODE ***xlstack;
- extern NODE *s_unbound;
- extern NODE *true;
-
- /* external routines */
- extern int eq(),eql(),equal();
-
- /* forward declarations */
- FORWARD NODE *cxr();
- FORWARD NODE *nth(),*assoc();
- FORWARD NODE *subst(),*sublis(),*map();
- FORWARD NODE *cequal();
-
- /* cxr functions */
- NODE *xcar(args) NODE *args; { return (cxr(args,"a")); }
- NODE *xcdr(args) NODE *args; { return (cxr(args,"d")); }
-
- /* cxxr functions */
- NODE *xcaar(args) NODE *args; { return (cxr(args,"aa")); }
- NODE *xcadr(args) NODE *args; { return (cxr(args,"da")); }
- NODE *xcdar(args) NODE *args; { return (cxr(args,"ad")); }
- NODE *xcddr(args) NODE *args; { return (cxr(args,"dd")); }
-
- /* cxxxr functions */
- NODE *xcaaar(args) NODE *args; { return (cxr(args,"aaa")); }
- NODE *xcaadr(args) NODE *args; { return (cxr(args,"daa")); }
- NODE *xcadar(args) NODE *args; { return (cxr(args,"ada")); }
- NODE *xcaddr(args) NODE *args; { return (cxr(args,"dda")); }
- NODE *xcdaar(args) NODE *args; { return (cxr(args,"aad")); }
- NODE *xcdadr(args) NODE *args; { return (cxr(args,"dad")); }
- NODE *xcddar(args) NODE *args; { return (cxr(args,"add")); }
- NODE *xcdddr(args) NODE *args; { return (cxr(args,"ddd")); }
-
- /* cxxxxr functions */
- NODE *xcaaaar(args) NODE *args; { return (cxr(args,"aaaa")); }
- NODE *xcaaadr(args) NODE *args; { return (cxr(args,"daaa")); }
- NODE *xcaadar(args) NODE *args; { return (cxr(args,"adaa")); }
- NODE *xcaaddr(args) NODE *args; { return (cxr(args,"ddaa")); }
- NODE *xcadaar(args) NODE *args; { return (cxr(args,"aada")); }
- NODE *xcadadr(args) NODE *args; { return (cxr(args,"dada")); }
- NODE *xcaddar(args) NODE *args; { return (cxr(args,"adda")); }
- NODE *xcadddr(args) NODE *args; { return (cxr(args,"ddda")); }
- NODE *xcdaaar(args) NODE *args; { return (cxr(args,"aaad")); }
- NODE *xcdaadr(args) NODE *args; { return (cxr(args,"daad")); }
- NODE *xcdadar(args) NODE *args; { return (cxr(args,"adad")); }
- NODE *xcdaddr(args) NODE *args; { return (cxr(args,"ddad")); }
- NODE *xcddaar(args) NODE *args; { return (cxr(args,"aadd")); }
- NODE *xcddadr(args) NODE *args; { return (cxr(args,"dadd")); }
- NODE *xcdddar(args) NODE *args; { return (cxr(args,"addd")); }
- NODE *xcddddr(args) NODE *args; { return (cxr(args,"dddd")); }
-
- /* cxr - common car/cdr routine */
- LOCAL NODE *cxr(args,adstr)
- NODE *args; char *adstr;
- {
- NODE *list;
-
- /* get the list */
- list = xlmatch(LIST,&args);
- xllastarg(args);
-
- /* perform the car/cdr operations */
- while (*adstr && consp(list))
- list = (*adstr++ == 'a' ? car(list) : cdr(list));
-
- /* make sure the operation succeeded */
- if (*adstr && list)
- xlfail("bad argument");
-
- /* return the result */
- return (list);
- }
-
- /* xcons - construct a new list cell */
- NODE *xcons(args)
- NODE *args;
- {
- NODE *arg1,*arg2;
-
- /* get the two arguments */
- arg1 = xlarg(&args);
- arg2 = xlarg(&args);
- xllastarg(args);
-
- /* construct a new list element */
- return (cons(arg1,arg2));
- }
-
- /* xlist - built a list of the arguments */
- NODE *xlist(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*list,*val,*last,*lptr;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&list,&val,NULL);
-
- /* initialize */
- arg = args;
-
- /* evaluate and append each argument */
- for (last = NIL; arg; last = lptr) {
-
- /* evaluate the next argument */
- val = xlarg(&arg);
-
- /* append this argument to the end of the list */
- lptr = consa(val);
- if (last == NIL)
- list = lptr;
- else
- rplacd(last,lptr);
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the list */
- return (list);
- }
-
- /* xappend - built-in function append */
- NODE *xappend(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*list,*last,*val,*lptr;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&list,&last,&val,NULL);
-
- /* initialize */
- arg = args;
-
- /* evaluate and append each argument */
- while (arg) {
-
- /* evaluate the next argument */
- list = xlmatch(LIST,&arg);
-
- /* append each element of this list to the result list */
- while (consp(list)) {
-
- /* append this element */
- lptr = consa(car(list));
- if (last == NIL)
- val = lptr;
- else
- rplacd(last,lptr);
-
- /* save the new last element */
- last = lptr;
-
- /* move to the next element */
- list = cdr(list);
- }
- }
-
- /* restore previous stack frame */
- xlstack = oldstk;
-
- /* return the list */
- return (val);
- }
-
- /* xreverse - built-in function reverse */
- NODE *xreverse(args)
- NODE *args;
- {
- NODE ***oldstk,*list,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&list,&val,NULL);
-
- /* get the list to reverse */
- list = xlmatch(LIST,&args);
- xllastarg(args);
-
- /* append each element of this list to the result list */
- while (consp(list)) {
-
- /* append this element */
- val = cons(car(list),val);
-
- /* move to the next element */
- list = cdr(list);
- }
-
- /* restore previous stack frame */
- xlstack = oldstk;
-
- /* return the list */
- return (val);
- }
-
- /* xlast - return the last cons of a list */
- NODE *xlast(args)
- NODE *args;
- {
- NODE *list;
-
- /* get the list */
- list = xlmatch(LIST,&args);
- xllastarg(args);
-
- /* find the last cons */
- while (consp(list) && cdr(list))
- list = cdr(list);
-
- /* return the last element */
- return (list);
- }
-
- /* xmember - built-in function 'member' */
- NODE *xmember(args)
- NODE *args;
- {
- NODE ***oldstk,*x,*list,*fcn,*val;
- int tresult;
-
- /* create a new stack frame */
- oldstk = xlsave(&x,&list,&fcn,NULL);
-
- /* get the expression to look for and the list */
- x = xlarg(&args);
- list = xlmatch(LIST,&args);
- xltest(&fcn,&tresult,&args);
- xllastarg(args);
-
- /* look for the expression */
- for (val = NIL; consp(list); list = cdr(list))
- if (dotest(x,car(list),fcn) == tresult) {
- val = list;
- break;
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xassoc - built-in function 'assoc' */
- NODE *xassoc(args)
- NODE *args;
- {
- NODE ***oldstk,*x,*alist,*fcn,*pair,*val;
- int tresult;
-
- /* create a new stack frame */
- oldstk = xlsave(&x,&alist,&fcn,NULL);
-
- /* get the expression to look for and the association list */
- x = xlarg(&args);
- alist = xlmatch(LIST,&args);
- xltest(&fcn,&tresult,&args);
- xllastarg(args);
-
- /* look for the expression */
- for (val = NIL; consp(alist); alist = cdr(alist))
- if ((pair = car(alist)) && consp(pair))
- if (dotest(x,car(pair),fcn) == tresult) {
- val = pair;
- break;
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xsubst - substitute one expression for another */
- NODE *xsubst(args)
- NODE *args;
- {
- NODE ***oldstk,*to,*from,*expr,*fcn,*val;
- int tresult;
-
- /* create a new stack frame */
- oldstk = xlsave(&to,&from,&expr,&fcn,NULL);
-
- /* get the to value, the from value and the expression */
- to = xlarg(&args);
- from = xlarg(&args);
- expr = xlarg(&args);
- xltest(&fcn,&tresult,&args);
- xllastarg(args);
-
- /* do the substitution */
- val = subst(to,from,expr,fcn,tresult);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* subst - substitute one expression for another */
- LOCAL NODE *subst(to,from,expr,fcn,tresult)
- NODE *to,*from,*expr,*fcn; int tresult;
- {
- NODE ***oldstk,*carval,*cdrval,*val;
-
- if (dotest(expr,from,fcn) == tresult)
- val = to;
- else if (consp(expr)) {
- oldstk = xlsave(&carval,&cdrval,NULL);
- carval = subst(to,from,car(expr),fcn,tresult);
- cdrval = subst(to,from,cdr(expr),fcn,tresult);
- val = cons(carval,cdrval);
- xlstack = oldstk;
- }
- else
- val = expr;
- return (val);
- }
-
- /* xsublis - substitute using an association list */
- NODE *xsublis(args)
- NODE *args;
- {
- NODE ***oldstk,*alist,*expr,*fcn,*val;
- int tresult;
-
- /* create a new stack frame */
- oldstk = xlsave(&alist,&expr,&fcn,NULL);
-
- /* get the assocation list and the expression */
- alist = xlmatch(LIST,&args);
- expr = xlarg(&args);
- xltest(&fcn,&tresult,&args);
- xllastarg(args);
-
- /* do the substitution */
- val = sublis(alist,expr,fcn,tresult);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* sublis - substitute using an association list */
- LOCAL NODE *sublis(alist,expr,fcn,tresult)
- NODE *alist,*expr,*fcn; int tresult;
- {
- NODE ***oldstk,*carval,*cdrval,*val;
-
- if (val = assoc(expr,alist,fcn,tresult))
- val = cdr(val);
- else if (consp(expr)) {
- oldstk = xlsave(&carval,&cdrval,NULL);
- carval = sublis(alist,car(expr),fcn,tresult);
- cdrval = sublis(alist,cdr(expr),fcn,tresult);
- val = cons(carval,cdrval);
- xlstack = oldstk;
- }
- else
- val = expr;
- return (val);
- }
-
- /* assoc - find a pair in an association list */
- LOCAL NODE *assoc(expr,alist,fcn,tresult)
- NODE *expr,*alist,*fcn; int tresult;
- {
- NODE *pair;
-
- for (; consp(alist); alist = cdr(alist))
- if ((pair = car(alist)) && consp(pair))
- if (dotest(expr,car(pair),fcn) == tresult)
- return (pair);
- return (NIL);
- }
-
- /* xremove - built-in function 'remove' */
- NODE *xremove(args)
- NODE *args;
- {
- NODE ***oldstk,*x,*list,*fcn,*val,*p,*last;
- int tresult;
-
- /* create a new stack frame */
- oldstk = xlsave(&x,&list,&fcn,&val,NULL);
-
- /* get the expression to remove and the list */
- x = xlarg(&args);
- list = xlmatch(LIST,&args);
- xltest(&fcn,&tresult,&args);
- xllastarg(args);
-
- /* remove matches */
- while (consp(list)) {
-
- /* check to see if this element should be deleted */
- if (dotest(x,car(list),fcn) != tresult) {
- p = consa(car(list));
- if (val) rplacd(last,p);
- else val = p;
- last = p;
- }
-
- /* move to the next element */
- list = cdr(list);
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the updated list */
- return (val);
- }
-
- /* dotest - call a test function */
- int dotest(arg1,arg2,fcn)
- NODE *arg1,*arg2,*fcn;
- {
- NODE ***oldstk,*args,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&args,NULL);
-
- /* build an argument list */
- args = consa(arg1);
- rplacd(args,consa(arg2));
-
- /* apply the test function */
- val = xlapply(fcn,args);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result of the test */
- return (val != NIL);
- }
-
- /* xnth - return the nth element of a list */
- NODE *xnth(args)
- NODE *args;
- {
- return (nth(args,TRUE));
- }
-
- /* xnthcdr - return the nth cdr of a list */
- NODE *xnthcdr(args)
- NODE *args;
- {
- return (nth(args,FALSE));
- }
-
- /* nth - internal nth function */
- LOCAL NODE *nth(args,carflag)
- NODE *args; int carflag;
- {
- NODE *list;
- int n;
-
- /* get n and the list */
- if ((n = getfixnum(xlmatch(INT,&args))) < 0)
- xlfail("bad argument");
- if ((list = xlmatch(LIST,&args)) == NIL)
- xlfail("bad argument");
- xllastarg(args);
-
- /* find the nth element */
- while (consp(list) && n--)
- list = cdr(list);
-
- /* return the list beginning at the nth element */
- return (carflag && consp(list) ? car(list) : list);
- }
-
- /* xlength - return the length of a list or string */
- NODE *xlength(args)
- NODE *args;
- {
- NODE *arg;
- int n;
-
- /* get the list or string */
- arg = xlarg(&args);
- xllastarg(args);
-
- /* find the length of a list */
- if (listp(arg))
- for (n = 0; consp(arg); n++)
- arg = cdr(arg);
-
- /* find the length of a string */
- else if (stringp(arg))
- n = strlen(getstring(arg));
-
- /* find the length of a vector */
- else if (vectorp(arg))
- n = getsize(arg);
-
- /* otherwise, bad argument type */
- else
- xlerror("bad argument type",arg);
-
- /* return the length */
- return (cvfixnum((FIXNUM)n));
- }
-
- /* xmapc - built-in function 'mapc' */
- NODE *xmapc(args)
- NODE *args;
- {
- return (map(args,TRUE,FALSE));
- }
-
- /* xmapcar - built-in function 'mapcar' */
- NODE *xmapcar(args)
- NODE *args;
- {
- return (map(args,TRUE,TRUE));
- }
-
- /* xmapl - built-in function 'mapl' */
- NODE *xmapl(args)
- NODE *args;
- {
- return (map(args,FALSE,FALSE));
- }
-
- /* xmaplist - built-in function 'maplist' */
- NODE *xmaplist(args)
- NODE *args;
- {
- return (map(args,FALSE,TRUE));
- }
-
- /* map - internal mapping function */
- LOCAL NODE *map(args,carflag,valflag)
- NODE *args; int carflag,valflag;
- {
- NODE ***oldstk,*fcn,*lists,*arglist,*val,*last,*p,*x,*y;
-
- /* create a new stack frame */
- oldstk = xlsave(&fcn,&lists,&arglist,&val,NULL);
-
- /* get the function to apply and the first list */
- fcn = xlarg(&args);
- lists = xlmatch(LIST,&args);
-
- /* save the first list if not saving function values */
- if (!valflag)
- val = lists;
-
- /* set up the list of argument lists */
- lists = consa(lists);
-
- /* get the remaining argument lists */
- while (args) {
- lists = consd(lists);
- rplaca(lists,xlmatch(LIST,&args));
- }
-
- /* if the function is a symbol, get its value */
- if (symbolp(fcn))
- fcn = xleval(fcn);
-
- /* loop through each of the argument lists */
- for (;;) {
-
- /* build an argument list from the sublists */
- arglist = NIL;
- for (x = lists; x && (y = car(x)) && consp(y); x = cdr(x)) {
- arglist = consd(arglist);
- rplaca(arglist,carflag ? car(y) : y);
- rplaca(x,cdr(y));
- }
-
- /* quit if any of the lists were empty */
- if (x) break;
-
- /* apply the function to the arguments */
- if (valflag) {
- p = consa(NIL);
- if (val) rplacd(last,p);
- else val = p;
- rplaca(p,xlapply(fcn,arglist));
- last = p;
- }
- else
- xlapply(fcn,arglist);
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last test expression value */
- return (val);
- }
-
- /* xrplca - replace the car of a list node */
- NODE *xrplca(args)
- NODE *args;
- {
- NODE *list,*newcar;
-
- /* get the list and the new car */
- if ((list = xlmatch(LIST,&args)) == NIL)
- xlfail("bad argument");
- newcar = xlarg(&args);
- xllastarg(args);
-
- /* replace the car */
- rplaca(list,newcar);
-
- /* return the list node that was modified */
- return (list);
- }
-
- /* xrplcd - replace the cdr of a list node */
- NODE *xrplcd(args)
- NODE *args;
- {
- NODE *list,*newcdr;
-
- /* get the list and the new cdr */
- if ((list = xlmatch(LIST,&args)) == NIL)
- xlfail("bad argument");
- newcdr = xlarg(&args);
- xllastarg(args);
-
- /* replace the cdr */
- rplacd(list,newcdr);
-
- /* return the list node that was modified */
- return (list);
- }
-
- /* xnconc - destructively append lists */
- NODE *xnconc(args)
- NODE *args;
- {
- NODE *list,*last,*val;
-
- /* concatenate each argument */
- for (val = NIL; args; ) {
-
- /* concatenate this list */
- if (list = xlmatch(LIST,&args)) {
-
- /* check for this being the first non-empty list */
- if (val)
- rplacd(last,list);
- else
- val = list;
-
- /* find the end of the list */
- while (consp(cdr(list)))
- list = cdr(list);
-
- /* save the new last element */
- last = list;
- }
- }
-
- /* return the list */
- return (val);
- }
-
- /* xdelete - built-in function 'delete' */
- NODE *xdelete(args)
- NODE *args;
- {
- NODE ***oldstk,*x,*list,*fcn,*last,*val;
- int tresult;
-
- /* create a new stack frame */
- oldstk = xlsave(&x,&list,&fcn,NULL);
-
- /* get the expression to delete and the list */
- x = xlarg(&args);
- list = xlmatch(LIST,&args);
- xltest(&fcn,&tresult,&args);
- xllastarg(args);
-
- /* delete leading matches */
- while (consp(list)) {
- if (dotest(x,car(list),fcn) != tresult)
- break;
- list = cdr(list);
- }
- val = last = list;
-
- /* delete embedded matches */
- if (consp(list)) {
-
- /* skip the first non-matching element */
- list = cdr(list);
-
- /* look for embedded matches */
- while (consp(list)) {
-
- /* check to see if this element should be deleted */
- if (dotest(x,car(list),fcn) == tresult)
- rplacd(last,cdr(list));
- else
- last = list;
-
- /* move to the next element */
- list = cdr(list);
- }
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the updated list */
- return (val);
- }
-
- /* xatom - is this an atom? */
- NODE *xatom(args)
- NODE *args;
- {
- NODE *arg;
- arg = xlarg(&args);
- xllastarg(args);
- return (atom(arg) ? true : NIL);
- }
-
- /* xsymbolp - is this an symbol? */
- NODE *xsymbolp(args)
- NODE *args;
- {
- NODE *arg;
- arg = xlarg(&args);
- xllastarg(args);
- return (arg == NIL || symbolp(arg) ? true : NIL);
- }
-
- /* xnumberp - is this a number? */
- NODE *xnumberp(args)
- NODE *args;
- {
- NODE *arg;
- arg = xlarg(&args);
- xllastarg(args);
- return (fixp(arg) || floatp(arg) ? true : NIL);
- }
-
- /* xboundp - is this a value bound to this symbol? */
- NODE *xboundp(args)
- NODE *args;
- {
- NODE *sym;
- sym = xlmatch(SYM,&args);
- xllastarg(args);
- return (getvalue(sym) == s_unbound ? NIL : true);
- }
-
- /* xnull - is this null? */
- NODE *xnull(args)
- NODE *args;
- {
- NODE *arg;
- arg = xlarg(&args);
- xllastarg(args);
- return (null(arg) ? true : NIL);
- }
-
- /* xlistp - is this a list? */
- NODE *xlistp(args)
- NODE *args;
- {
- NODE *arg;
- arg = xlarg(&args);
- xllastarg(args);
- return (listp(arg) ? true : NIL);
- }
-
- /* xconsp - is this a cons? */
- NODE *xconsp(args)
- NODE *args;
- {
- NODE *arg;
- arg = xlarg(&args);
- xllastarg(args);
- return (consp(arg) ? true : NIL);
- }
-
- /* xeq - are these equal? */
- NODE *xeq(args)
- NODE *args;
- {
- return (cequal(args,eq));
- }
-
- /* xeql - are these equal? */
- NODE *xeql(args)
- NODE *args;
- {
- return (cequal(args,eql));
- }
-
- /* xequal - are these equal? */
- NODE *xequal(args)
- NODE *args;
- {
- return (cequal(args,equal));
- }
-
- /* cequal - common eq/eql/equal function */
- LOCAL NODE *cequal(args,fcn)
- NODE *args; int (*fcn)();
- {
- NODE *arg1,*arg2;
-
- /* get the two arguments */
- arg1 = xlarg(&args);
- arg2 = xlarg(&args);
- xllastarg(args);
-
- /* compare the arguments */
- return ((*fcn)(arg1,arg2) ? true : NIL);
- }